package com.example.demo.webservice.service.approval;

import com.example.demo.data.approval.Approval;
import com.example.demo.data.approval.ApprovalBO;
import com.example.demo.data.holidays.Holidays;
import com.example.demo.data.leave.Leave;
import com.example.demo.webservice.repository.ApprovalRepository;
import com.example.demo.webservice.repository.HolidaysRepository;
import com.example.demo.webservice.repository.LeaveRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.util.List;
import java.util.Map;

@Service
public class ApprovalServiceImpl implements ApprovalService{
    private ApprovalRepository approvalRepository;
    private LeaveRepository leaveRepository;
    private HolidaysRepository holidaysRepository;
    private final int SECOND_CONVERT = 60 * 60 * 24 * 1000;
    private final int SHORT_HOLIDAYS = 3;

    @Autowired
    public ApprovalServiceImpl(ApprovalRepository approvalRepository,
                               LeaveRepository leaveRepository, HolidaysRepository holidaysRepository){
        this.approvalRepository = approvalRepository;
        this.leaveRepository = leaveRepository;
        this.holidaysRepository = holidaysRepository;
    }
    @Override
    public List<Approval> getAllApproval() {
        return approvalRepository.getAllApproval();
    }

    @Override
    public List<Approval> getApprovalByID(Long empID, Long appID) {
        return approvalRepository.getApprovalByID(empID, appID);
    }

    @Override
    public Approval addApproval(Approval approval) {

        return approvalRepository.addApproval(approval);
    }

    @Override
    public Approval editApproval(Approval approval) {
        long appID = approval.getAppID();
        long empID = approval.getEmpID();
        Map<String, Object> approvalMap = approvalRepository.queryByAppID(appID, empID);
        Approval approvalBO = new ApprovalBO();
        BOFilled(approvalBO, approvalMap);
        BOUpdate(approvalBO, approval);
        return approvalRepository.editApproval(appID,approvalBO);
    }

    @Override
    public ResponseEntity deleteApproval(long appID, long empID) {
        return approvalRepository.deleteApproval(appID, empID);
    }

    public void BOFilled(Approval approvalBO, Map<String, Object> approvalMap){
        for(Map.Entry<String, Object> entry: approvalMap.entrySet()){
            switch (entry.getKey()){
                case "empId":
                    approvalBO.setEmpID((Long)entry.getValue());
                    break;
                case "approvalType":
                    approvalBO.setType((Integer) entry.getValue());
                    break;
                case "approval":
                    approvalBO.setApproval((Boolean)entry.getValue());
                    break;
                case "comment":
                    approvalBO.setComment((String) entry.getValue());
                    break;
                case "time":
                    approvalBO.setTime((Date) entry.getValue());
                    break;
            }
        }
    }
    public void BOUpdate(Approval approvalBO, Approval approvalVO){
        if(approvalVO.getComment() != null){
            approvalBO.setComment(approvalVO.getComment());
        }
        if(approvalVO.getApproval() != null){
            approvalBO.setApproval(approvalVO.getApproval());
        }
        if(approvalVO.getType() != null){
            approvalBO.setType(approvalVO.getType());
        }
        if(approvalVO.getEmpID() != null){
            approvalBO.setEmpID(approvalVO.getEmpID());
        }
        if(approvalVO.getTime() != null){
            approvalBO.setTime(approvalVO.getTime());
        }
    }
    public void UpdateRestHolidays(Approval approval){
        Leave leaveInfo = leaveRepository.getLeaveInfoByAppID(approval.getAppID());
        Holidays holidaysInfo = holidaysRepository.getHolidaysInfoByID(leaveInfo.getEmpID());
        int days = (int)(leaveInfo.getEndTime().getTime() - leaveInfo.getStartTime().getTime()) / SECOND_CONVERT + 1;
        if(approval.getType() == Approval.VICE_GENERAL_MANAGER_APPROVAL && days <= SHORT_HOLIDAYS){
            holidaysRepository.updateRestHolidays(days, leaveInfo.getEmpID());
        } else if(approval.getType() == Approval.GENERAL_MANAGER_APPROVAL &&
                days > SHORT_HOLIDAYS){
            holidaysRepository.updateRestHolidays(holidaysInfo.getRestHolidays() - days, leaveInfo.getEmpID());
        }
    }
    public void checkReturnHolidays(int oldApprovalType, int newApprovalType, long appID){
        Leave leaveInfo = leaveRepository.getLeaveInfoByAppID(appID);
        Holidays holidaysInfo = holidaysRepository.getHolidaysInfoByID(leaveInfo.getEmpID());
        int days = (int)(leaveInfo.getEndTime().getTime() - leaveInfo.getStartTime().getTime()) / SECOND_CONVERT + 1;
        boolean needReturn = false;
        if(oldApprovalType == Approval.VICE_GENERAL_MANAGER_APPROVAL &&
                days <= SHORT_HOLIDAYS && newApprovalType == Approval.REFUSE ){
            needReturn = true;
        } else if(oldApprovalType == Approval.GENERAL_MANAGER_APPROVAL &&
                 days > SHORT_HOLIDAYS && newApprovalType == Approval.REFUSE ){
            needReturn = true;
        }
        if(needReturn){
            holidaysRepository.updateRestHolidays(holidaysInfo.getRestHolidays() + days, leaveInfo.getEmpID());
        }
    }
}
